package monteCarloMulti;

import gui.Menu;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

import monteCarloSingle.MonteCarloSimulation;

public class MainMultiThreads {
	public double compute()
			throws InterruptedException, ExecutionException {

		final int numberOfCores = Runtime.getRuntime().availableProcessors();
		final double blockingCoefficient = 0.2;
		final int poolSize = (int) (numberOfCores / (1 - blockingCoefficient));

		System.out.println("Number of Cores available is " + numberOfCores);
		System.out.println("Pool size is " + poolSize);

		double result = 0;
		final Menu m = new Menu();

		final List<Callable<Double>> partitions = new ArrayList<Callable<Double>>();

		while (true) {
			if (m.isReady()) {
				result = 0;
				partitions.clear();
				System.out.println(m.getnSimulations() + " simulations");
				long begin = System.nanoTime();

				for (int i = 0; i < m.getnSimulations(); i++) {
					partitions.add(new Callable<Double>() {
						public Double call() throws Exception {
							return MonteCarloSimulation
									.MonteCarloStandardOption("c", m.getS(),
											m.getvalueX(), m.getT(), m.getR(),
											m.getB(), m.getV(), m.getnSteps());
						}
					});
				}

				final ExecutorService executorPool = Executors
						.newFixedThreadPool(poolSize);

				final List<Future<Double>> values = executorPool
						.invokeAll(partitions, 100000, TimeUnit.SECONDS);
				for (final Future<Double> value : values)
					result += value.get();

				executorPool.shutdown();

				result = result / m.getnSimulations();
				long end = System.nanoTime();

				m.getLblresult().setText("result : ");
				m.getTime().setText("time (second) : ");
				m.getLblresult().setText(m.getLblresult().getText() + result);
				m.getTime().setText(
						m.getTime().getText() + (end - begin) / 1.0e9);
				m.setReady(false);
				System.out.println(result);
				System.out.println("temps de calcul(secondes) : "
						+ (end - begin) / 1.0e9);
			}
		}
	}

	public static void main(final String[] args) throws ExecutionException,
			InterruptedException, IOException {
		new MainMultiThreads().compute();
	}
}
